package com.zhanglijie.base.sync.aqs;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedLongSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

import com.sun.javaws.exceptions.ErrorCodeResponseException;

/**
 * @author zhanglijie
 * @version 1.0
 * @since 1.1.0 2022/6/18 0018 0:55
 */
public class MyUnfairLock implements Lock {
    private MySync mySync = null;
    public MyUnfairLock(){
        mySync = new MySync();
    }
    private static class MySync extends AbstractQueuedLongSynchronizer{
      public void lock(){
          //拿到锁
          if(compareAndSetState(0,1)){
              setExclusiveOwnerThread(Thread.currentThread());
          }else{//没有拿到 ，给参数一 表示只能一个线程进入同步代码块
              acquire(1);
          }
      }
        @Override
        protected boolean tryAcquire(long arg) {
            Thread currentThread = Thread.currentThread();
            long state = getState();
            if(state == 0){
                if(compareAndSetState(0,arg)){
                    setExclusiveOwnerThread(currentThread);
                    return true;
                }
            }else if(currentThread == getExclusiveOwnerThread()){
                //重入
                long next  = state+arg;
                if(next<0){
                    throw new Error("参数有误");
                }
                setState(state);
                return true;
            }
            return false;
        }

        public void unlock() {
          release(1);
        }
        @Override
        protected boolean tryRelease(long arg) {
            long newState = getState()- arg;
            if(getExclusiveOwnerThread() != Thread.currentThread()){
                throw new Error("not self thread can not release lock");
            }
            boolean free = false;
            if(newState == 0){
                free = true;
                setState(0L);
                setExclusiveOwnerThread(null);
            }
            return free;
        }
    }
    @Override
    public void lock() {
        mySync.lock();
    }

    @Override
    public void unlock() {
        mySync.unlock();
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }
    @Override
    public boolean tryLock() {
        return false;
    }
    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }
    @Override
    public Condition newCondition() {
        return null;
    }
}
